package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.service.*;
import com.zzyl.nursing.util.CodeGenerator;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.CheckInMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * 入住Service业务层处理
 * 
 * @author alexis
 * @date 2025-06-07
 */
@Service
@Slf4j
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;

    @Autowired
    private IElderService elderService;

    @Autowired
    private IBedService bedService;

    @Autowired
    private IContractService contractService;

    @Autowired
    private ICheckInConfigService cbService;



    /**
     * 查询入住
     * 
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckIn selectCheckInById(Long id)
    {
        return checkInMapper.selectById(id);
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return checkInMapper.insert(checkIn);
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return checkInMapper.updateById(checkIn);
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return checkInMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return checkInMapper.deleteById(id);
    }

    @Override
    public void checkInAply(CheckInApplyDto dto) {
        //校验老人是否入住？入住了就直接抛异常，没入住继续执行下述代码
        //select * from elder where status=?
        Elder queryElder = elderService.lambdaQuery()
                .eq(Elder::getIdCardNo, dto.getCheckInElderDto().getIdCardNo())
                .one();
        if(queryElder!=null&&queryElder.getStatus()==1){
            throw new RuntimeException("该老人已入住，怎么还要二次申请入住呢？");
        }
        //更新床位状态为已入住
        //update bed set bed_status=1 where id = ?
        //首先先去创建Bed对象，调用Mybatis-Plus的updateById（bed）方法去更新
        Bed bed = new Bed();
        bed.setId(dto.getCheckInConfigDto().getBedId());
        bed.setBedStatus(1);
        bedService.updateById(bed);
        //但是Mybatis-Plus的updateById（bed）方法需要bed包含id，它内部时首先根据id找到要修改的数据，然后在更新数据
        //但是如果找不到，或者没有id，就不会
        //根据bedId查询床，如没有，则抛异常
        Bed dbBed = bedService.getById(dto.getCheckInConfigDto().getBedId());
        if(dbBed==null){
            throw new RuntimeException("没有这张床");
        }
        //新增或更新老人
        Elder newElder = BeanUtil.toBean(dto.getCheckInElderDto(), Elder.class);
        newElder.setStatus(1);
        newElder.setBedId(dbBed.getId());
        newElder.setBedNumber(dbBed.getBedNumber());
        if(queryElder!=null){
            //说明老人原本就在数据库中，不需要添加，只需要更新，那么就需要赋给id
            newElder.setId(queryElder.getId());
        }
        elderService.saveOrUpdate(newElder);//如果这个对象的id在数据库里面有，那么就更新。否则新增
        //新增签约办理
        Contract newContract = BeanUtil.toBean(dto.getCheckInContractDto(), Contract.class);
        newContract.setElderId(newElder.getId());
        newContract.setContractNumber("HT"+ CodeGenerator.generateContractNumber());
        newContract.setElderName(newElder.getName());
        LocalDateTime startDate = dto.getCheckInConfigDto().getStartDate();
        newContract.setStartDate(startDate);
        newContract.setEndDate(dto.getCheckInConfigDto().getEndDate());
        newContract.setStatus(startDate.isBefore(LocalDateTime.now())?1:0);
        contractService.save(newContract);
        //新增入住信息
        CheckIn checkIn = BeanUtil.toBean(dto.getCheckInConfigDto(), CheckIn.class);
        checkIn.setElderName(newElder.getName());
        checkIn.setElderId(newElder.getId());
        checkIn.setIdCardNo(newElder.getIdCardNo());
        checkIn.setBedNumber(dbBed.getBedNumber());
        checkIn.setStatus(0);
        checkIn.setRemark(JSONUtil.toJsonStr(dto.getElderFamilyDtoList()));
        save(checkIn);
        //新增入住配置
        CheckInConfig checkInConfig = BeanUtil.toBean(dto.getCheckInConfigDto(), CheckInConfig.class);
        checkInConfig.setCheckInId(checkIn.getId());

        cbService.save(checkInConfig);
    }

    @Override
    public CheckInDetailVo checkDetail(Long id) {
        CheckIn checkIn = lambdaQuery().eq(CheckIn::getId, id).one();
        if(checkIn==null){
            throw new RuntimeException("入住表查询失败");
        }
        //根据id查询老头select * from elder where id =?
        Elder queryElder = elderService.lambdaQuery()
                .eq(Elder::getId, checkIn.getElderId())
                .one();
        if(queryElder==null){
            throw new RuntimeException("没有查到该老人的信息，请联系工作人员");
        }
        //转换成对应的vo返回，同时根据身份证号计算年龄
        CheckInElderVo checkInElderVo = BeanUtil.toBean(queryElder, CheckInElderVo.class);
        Integer age=-1;
        String idCardNo = queryElder.getIdCardNo();
        age = getAgeByIdCard(idCardNo);

        checkInElderVo.setAge(age);
        //将check_in表中的remark字段反序列化后赋值给elderFamilyVoList
        //select remark from check_in where elder_id = CheckInElderVo.getID()
        String remark = checkIn.getRemark();
        log.info("remark============:{}",remark);
        List<ElderFamilyVo> elderFamilyVoList = JSONUtil.toList(remark, ElderFamilyVo.class);
        //接下来要返回CheckInConfigVo类型的VO，但是这是根据check_in_id这个去查找的
        //而check_in_id是在check_in这个表中的，所以要现根据queryElder获取对应的check_in
        //select * from check_in_config where check_in_id=?
        //select id from check_in where elder_id = queryElder.getId()
//        CheckIn checkIn = lambdaQuery().eq(CheckIn::getElderId, queryElder.getId()).one();

        CheckInConfig checkInConfig = cbService.lambdaQuery().eq(CheckInConfig::getCheckInId, checkIn.getId()).one();
        CheckInConfigVo checkInConfigVo = BeanUtil.toBean(checkInConfig, CheckInConfigVo.class);
        checkInConfigVo.setBedNumber(queryElder.getBedNumber());
        //其中start_date和end_date在contract表中
        //select start_date,end_date from contract where elder_id=queryElder.getId()
        Contract contract = contractService.lambdaQuery().eq(Contract::getElderId, queryElder.getId()).one();
        checkInConfigVo.setStartDate(contract.getStartDate());
        checkInConfigVo.setEndDate(contract.getEndDate());
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
        checkInDetailVo.setCheckInElderVo(checkInElderVo);
        checkInDetailVo.setElderFamilyVoList(elderFamilyVoList);
        checkInDetailVo.setContract(contract);
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);
        return checkInDetailVo;
    }


    /**
     * 根据身份证号码获取年龄
     *
     * @param idCardNo 身份证号码
     * @return 年龄
     */
    public static Integer getAgeByIdCard(String idCardNo) {
        if (idCardNo == null || idCardNo.length() < 18) {
            return -1;
        }

        try {
            // 从身份证号中提取出生日期 (第7位到第14位)
            String birthDateStr = idCardNo.substring(6, 14);

            // 解析出生年月日
            int year = Integer.parseInt(birthDateStr.substring(0, 4));
            int month = Integer.parseInt(birthDateStr.substring(4, 6));
            int day = Integer.parseInt(birthDateStr.substring(6, 8));

            // 获取当前日期
            java.time.LocalDate currentDate = java.time.LocalDate.now();
            int currentYear = currentDate.getYear();
            int currentMonth = currentDate.getMonthValue();
            int currentDay = currentDate.getDayOfMonth();

            // 计算年龄
            int age = currentYear - year;

            // 如果当前月份小于出生月份，或者当前月份等于出生月份但当前日期小于出生日期，则年龄减1
            if (currentMonth < month || (currentMonth == month && currentDay < day)) {
                age--;
            }

            return age;
        } catch (Exception e) {
            // 解析失败返回-1
            return -1;
        }
    }

}
